{
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {
        "tags": [],
        "id": "tDpL4nb7Nzg1"
      },
      "source": [
        "# Digit Recognizer Notebook\n",
        "\n",
        "In this [Kaggle competition](https://www.kaggle.com/competitions/digit-recognizer/overview) \n",
        "\n",
        ">MNIST (\"Modified National Institute of Standards and Technology\") is the de facto “hello world” dataset of computer vision. Since its release in 1999, this classic dataset of handwritten images has served as the basis for benchmarking classification algorithms. As new machine learning techniques emerge, MNIST remains a reliable resource for researchers and learners alike.\n",
        "\n",
        ">In this competition, your goal is to correctly identify digits from a dataset of tens of thousands of handwritten images."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "tags": [],
        "id": "qADn_iJvNzhG"
      },
      "source": [
        "# Install necessary packages\n",
        "\n",
        "We can install the necessary package by either running `pip install --user <package_name>` or include everything in a `requirements.txt` file and run `pip install --user -r requirements.txt`. We have put the dependencies in a `requirements.txt` file so we will use the former method."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "tags": [
          "skip"
        ],
        "id": "4j2PhVZONzhH"
      },
      "outputs": [],
      "source": [
        "!pip install -r requirements.txt --quiet"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "tags": [],
        "id": "_CMbzFDvNzhI"
      },
      "source": [
        "# Imports\n",
        "\n",
        "In this section we import the packages we need for this example. Make it a habit to gather your imports in a single place. It will make your life easier if you are going to transform this notebook into a Kubeflow pipeline using Kale."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "tags": [
          "imports"
        ],
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "SW6nRo1yNzhJ",
        "outputId": "0433d9eb-7e86-4af0-b835-aa556c80472d"
      },
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "tensorflow version:  2.3.0\n"
          ]
        }
      ],
      "source": [
        "import os\n",
        "import datetime\n",
        "import numpy as np\n",
        "import pandas as pd\n",
        "import pickle\n",
        "import zipfile\n",
        "import matplotlib.pyplot as plt\n",
        "import seaborn as sns\n",
        "from sklearn.model_selection import train_test_split\n",
        "from sklearn.metrics import confusion_matrix\n",
        "\n",
        "import tensorflow as tf\n",
        "from tensorflow import keras, optimizers\n",
        "from tensorflow.keras.metrics import SparseCategoricalAccuracy\n",
        "from tensorflow.keras.losses import SparseCategoricalCrossentropy\n",
        "from tensorflow.keras import layers\n",
        "print(\"tensorflow version: \", tf.__version__)"
      ]
    },
    {
      "cell_type": "code",
      "source": [
        "# hyper parameters\n",
        "LR = 1e-3\n",
        "EPOCHS = 2\n",
        "BATCH_SIZE = 64\n",
        "CONV_DIM1 = 56\n",
        "CONV_DIM2 = 100"
      ],
      "metadata": {
        "id": "mJ8z7BVOCXjo"
      },
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "tags": [],
        "id": "kKkCTOLcNzhM"
      },
      "source": [
        "Set random seed for reproducibility and ignore warning messages."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "tags": [
          "skip"
        ],
        "id": "RzS7PO7UNzhM"
      },
      "outputs": [],
      "source": [
        "tf.random.set_seed(42)\n",
        "np.random.seed(42)\n",
        "\n",
        "tf.compat.v1.logging.set_verbosity(tf.compat.v1.logging.INFO)\n",
        "\n",
        "# Setting the graph style\n",
        "plt.rc('figure', autolayout=True)\n",
        "plt.rc('axes', titleweight='bold', \n",
        "        titlesize=15)\n",
        "\n",
        "plt.rc('font', size=12)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "tags": [],
        "id": "eZ_HkwkSNzhN"
      },
      "source": [
        "Download data"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "tags": [
          "block:download_data"
        ],
        "id": "wI06amnhNzhN"
      },
      "outputs": [],
      "source": [
        "import zipfile\n",
        "import wget\n",
        "import os\n",
        "\n",
        "# download files\n",
        "data_path = os.getcwd()\n",
        "\n",
        "# data link\n",
        "train_link = 'https://github.com/josepholaide/examples/blob/master/digit-recognition-kaggle-competition/data/train.csv.zip?raw=true'\n",
        "test_link = 'https://github.com/josepholaide/examples/blob/master/digit-recognition-kaggle-competition/data/test.csv.zip?raw=true'\n",
        "sample_submission = 'https://raw.githubusercontent.com/josepholaide/examples/master/digit-recognition-kaggle-competition/data/sample_submission.csv'\n",
        "\n",
        "# download data\n",
        "wget.download(train_link, f'{data_path}/train_csv.zip')\n",
        "wget.download(test_link, f'{data_path}/test_csv.zip')\n",
        "wget.download(sample_submission, f'{data_path}/sample_submission.csv')\n",
        "\n",
        "\n",
        "with zipfile.ZipFile(f\"{data_path}/train_csv.zip\",\"r\") as zip_ref:\n",
        "    zip_ref.extractall(data_path)\n",
        "\n",
        "with zipfile.ZipFile(f\"{data_path}/test_csv.zip\",\"r\") as zip_ref:\n",
        "    zip_ref.extractall(data_path)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "tags": [],
        "id": "5PXF1GJLNzhO"
      },
      "source": [
        "# Load and preprocess data\n",
        "\n",
        "In this section, we load z the dataset to get it in a ready-to-use form by the model. First, let us load and analyze the data."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "tags": [],
        "id": "DcPgFgfBNzhP"
      },
      "source": [
        "## Load data"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "tags": [],
        "id": "moKPeKgyNzhP"
      },
      "source": [
        "The data are in `csv` format, thus, we use the handy `read_csv` pandas method. There is one train data set and two test sets (one public and one private)."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "tags": [
          "block:load_data",
          "prev:download_data"
        ],
        "id": "emKOFYlGNzhP"
      },
      "outputs": [],
      "source": [
        "data_path = os.getcwd()\n",
        "\n",
        "# Data Path\n",
        "train_data_path = data_path + '/train.csv'\n",
        "test_data_path = data_path + '/test.csv'\n",
        "sample_submission_path = data_path + '/sample_submission.csv'\n",
        "\n",
        "\n",
        "# Loading dataset into pandas \n",
        "train_df = pd.read_csv(train_data_path)\n",
        "test_df = pd.read_csv(test_data_path)\n",
        "ss = pd.read_csv(sample_submission_path)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "tags": [],
        "id": "CUcsmEW6NzhQ"
      },
      "source": [
        "Let us now explore the data\n",
        "To this end, we use the pandas `head` method to visualize the 1st five rows of our data set."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "tags": [],
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 300
        },
        "id": "pIpFyYKbNzhR",
        "outputId": "fb0cc1f5-ffde-4424-8459-a0dd424f4849"
      },
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "   label  pixel0  pixel1  pixel2  pixel3  pixel4  pixel5  pixel6  pixel7  \\\n",
              "0      1       0       0       0       0       0       0       0       0   \n",
              "1      0       0       0       0       0       0       0       0       0   \n",
              "2      1       0       0       0       0       0       0       0       0   \n",
              "3      4       0       0       0       0       0       0       0       0   \n",
              "4      0       0       0       0       0       0       0       0       0   \n",
              "\n",
              "   pixel8  ...  pixel774  pixel775  pixel776  pixel777  pixel778  pixel779  \\\n",
              "0       0  ...         0         0         0         0         0         0   \n",
              "1       0  ...         0         0         0         0         0         0   \n",
              "2       0  ...         0         0         0         0         0         0   \n",
              "3       0  ...         0         0         0         0         0         0   \n",
              "4       0  ...         0         0         0         0         0         0   \n",
              "\n",
              "   pixel780  pixel781  pixel782  pixel783  \n",
              "0         0         0         0         0  \n",
              "1         0         0         0         0  \n",
              "2         0         0         0         0  \n",
              "3         0         0         0         0  \n",
              "4         0         0         0         0  \n",
              "\n",
              "[5 rows x 785 columns]"
            ],
            "text/html": [
              "\n",
              "  <div id=\"df-e3e32755-8b08-425e-bcbf-89132bcce712\">\n",
              "    <div class=\"colab-df-container\">\n",
              "      <div>\n",
              "<style scoped>\n",
              "    .dataframe tbody tr th:only-of-type {\n",
              "        vertical-align: middle;\n",
              "    }\n",
              "\n",
              "    .dataframe tbody tr th {\n",
              "        vertical-align: top;\n",
              "    }\n",
              "\n",
              "    .dataframe thead th {\n",
              "        text-align: right;\n",
              "    }\n",
              "</style>\n",
              "<table border=\"1\" class=\"dataframe\">\n",
              "  <thead>\n",
              "    <tr style=\"text-align: right;\">\n",
              "      <th></th>\n",
              "      <th>label</th>\n",
              "      <th>pixel0</th>\n",
              "      <th>pixel1</th>\n",
              "      <th>pixel2</th>\n",
              "      <th>pixel3</th>\n",
              "      <th>pixel4</th>\n",
              "      <th>pixel5</th>\n",
              "      <th>pixel6</th>\n",
              "      <th>pixel7</th>\n",
              "      <th>pixel8</th>\n",
              "      <th>...</th>\n",
              "      <th>pixel774</th>\n",
              "      <th>pixel775</th>\n",
              "      <th>pixel776</th>\n",
              "      <th>pixel777</th>\n",
              "      <th>pixel778</th>\n",
              "      <th>pixel779</th>\n",
              "      <th>pixel780</th>\n",
              "      <th>pixel781</th>\n",
              "      <th>pixel782</th>\n",
              "      <th>pixel783</th>\n",
              "    </tr>\n",
              "  </thead>\n",
              "  <tbody>\n",
              "    <tr>\n",
              "      <th>0</th>\n",
              "      <td>1</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "      <td>...</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>1</th>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "      <td>...</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>2</th>\n",
              "      <td>1</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "      <td>...</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>3</th>\n",
              "      <td>4</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "      <td>...</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>4</th>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "      <td>...</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "      <td>0</td>\n",
              "    </tr>\n",
              "  </tbody>\n",
              "</table>\n",
              "<p>5 rows × 785 columns</p>\n",
              "</div>\n",
              "      <button class=\"colab-df-convert\" onclick=\"convertToInteractive('df-e3e32755-8b08-425e-bcbf-89132bcce712')\"\n",
              "              title=\"Convert this dataframe to an interactive table.\"\n",
              "              style=\"display:none;\">\n",
              "        \n",
              "  <svg xmlns=\"http://www.w3.org/2000/svg\" height=\"24px\"viewBox=\"0 0 24 24\"\n",
              "       width=\"24px\">\n",
              "    <path d=\"M0 0h24v24H0V0z\" fill=\"none\"/>\n",
              "    <path d=\"M18.56 5.44l.94 2.06.94-2.06 2.06-.94-2.06-.94-.94-2.06-.94 2.06-2.06.94zm-11 1L8.5 8.5l.94-2.06 2.06-.94-2.06-.94L8.5 2.5l-.94 2.06-2.06.94zm10 10l.94 2.06.94-2.06 2.06-.94-2.06-.94-.94-2.06-.94 2.06-2.06.94z\"/><path d=\"M17.41 7.96l-1.37-1.37c-.4-.4-.92-.59-1.43-.59-.52 0-1.04.2-1.43.59L10.3 9.45l-7.72 7.72c-.78.78-.78 2.05 0 2.83L4 21.41c.39.39.9.59 1.41.59.51 0 1.02-.2 1.41-.59l7.78-7.78 2.81-2.81c.8-.78.8-2.07 0-2.86zM5.41 20L4 18.59l7.72-7.72 1.47 1.35L5.41 20z\"/>\n",
              "  </svg>\n",
              "      </button>\n",
              "      \n",
              "  <style>\n",
              "    .colab-df-container {\n",
              "      display:flex;\n",
              "      flex-wrap:wrap;\n",
              "      gap: 12px;\n",
              "    }\n",
              "\n",
              "    .colab-df-convert {\n",
              "      background-color: #E8F0FE;\n",
              "      border: none;\n",
              "      border-radius: 50%;\n",
              "      cursor: pointer;\n",
              "      display: none;\n",
              "      fill: #1967D2;\n",
              "      height: 32px;\n",
              "      padding: 0 0 0 0;\n",
              "      width: 32px;\n",
              "    }\n",
              "\n",
              "    .colab-df-convert:hover {\n",
              "      background-color: #E2EBFA;\n",
              "      box-shadow: 0px 1px 2px rgba(60, 64, 67, 0.3), 0px 1px 3px 1px rgba(60, 64, 67, 0.15);\n",
              "      fill: #174EA6;\n",
              "    }\n",
              "\n",
              "    [theme=dark] .colab-df-convert {\n",
              "      background-color: #3B4455;\n",
              "      fill: #D2E3FC;\n",
              "    }\n",
              "\n",
              "    [theme=dark] .colab-df-convert:hover {\n",
              "      background-color: #434B5C;\n",
              "      box-shadow: 0px 1px 3px 1px rgba(0, 0, 0, 0.15);\n",
              "      filter: drop-shadow(0px 1px 2px rgba(0, 0, 0, 0.3));\n",
              "      fill: #FFFFFF;\n",
              "    }\n",
              "  </style>\n",
              "\n",
              "      <script>\n",
              "        const buttonEl =\n",
              "          document.querySelector('#df-e3e32755-8b08-425e-bcbf-89132bcce712 button.colab-df-convert');\n",
              "        buttonEl.style.display =\n",
              "          google.colab.kernel.accessAllowed ? 'block' : 'none';\n",
              "\n",
              "        async function convertToInteractive(key) {\n",
              "          const element = document.querySelector('#df-e3e32755-8b08-425e-bcbf-89132bcce712');\n",
              "          const dataTable =\n",
              "            await google.colab.kernel.invokeFunction('convertToInteractive',\n",
              "                                                     [key], {});\n",
              "          if (!dataTable) return;\n",
              "\n",
              "          const docLinkHtml = 'Like what you see? Visit the ' +\n",
              "            '<a target=\"_blank\" href=https://colab.research.google.com/notebooks/data_table.ipynb>data table notebook</a>'\n",
              "            + ' to learn more about interactive tables.';\n",
              "          element.innerHTML = '';\n",
              "          dataTable['output_type'] = 'display_data';\n",
              "          await google.colab.output.renderOutput(dataTable, element);\n",
              "          const docLink = document.createElement('div');\n",
              "          docLink.innerHTML = docLinkHtml;\n",
              "          element.appendChild(docLink);\n",
              "        }\n",
              "      </script>\n",
              "    </div>\n",
              "  </div>\n",
              "  "
            ]
          },
          "metadata": {},
          "execution_count": 30
        }
      ],
      "source": [
        "train_df.head()"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "tags": [],
        "id": "oemlNSd5NzhR"
      },
      "source": [
        "# Data dimension\n",
        "lets check train and test dimensions"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "tags": [],
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "PFdfVUOqNzhR",
        "outputId": "423b7db3-5b21-432a-a627-f36d10636ab2"
      },
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "((42000, 785), (28000, 784))"
            ]
          },
          "metadata": {},
          "execution_count": 31
        }
      ],
      "source": [
        "train_df.shape, test_df.shape"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "tags": [],
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "6yj3lsJfNzhS",
        "outputId": "edae52d9-e848-4828-ee4c-ed3a40c8f026"
      },
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "all_data size is : (70000, 785)\n"
          ]
        }
      ],
      "source": [
        "# join train and test together\n",
        "ntrain = train_df.shape[0]\n",
        "ntest = test_df.shape[0]\n",
        "\n",
        "all_data = pd.concat((train_df, test_df)).reset_index(drop=True)\n",
        "print(\"all_data size is : {}\".format(all_data.shape))"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "tags": [],
        "id": "FcoN8PYnNzhT"
      },
      "source": [
        "## Preprocess data"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "tags": [],
        "id": "NufHxQh_NzhT"
      },
      "source": [
        "We are now ready to transform the data set and split the dataset into features and the target variables."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "tags": [
          "block:preprocess_data",
          "prev:load_data"
        ],
        "id": "VooYIAG8NzhT"
      },
      "outputs": [],
      "source": [
        "all_data_X = all_data.drop('label', axis=1)\n",
        "all_data_y = all_data.label"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "tags": [],
        "id": "OBelN6rGNzhU"
      },
      "outputs": [],
      "source": [
        "# Reshape image in 3 dimensions (height = 28px, width = 28px , channel = 1)\n",
        "all_data_X = all_data_X.values.reshape(-1,28,28,1)\n",
        "\n",
        "# Normalize the data\n",
        "all_data_X = all_data_X / 255.0"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "tags": [],
        "id": "k8ylkUOjNzhU"
      },
      "outputs": [],
      "source": [
        "#Get the new dataset\n",
        "X = all_data_X[:ntrain].copy()\n",
        "y = all_data_y[:ntrain].copy()"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "tags": [],
        "id": "9kufDVomNzhV"
      },
      "outputs": [],
      "source": [
        "# split the dataset\n",
        "X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.1, random_state=42)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "tags": [],
        "id": "Ntc43ItDNzhV"
      },
      "source": [
        "# Define and train the model\n",
        "\n",
        "we define models with convoolution and dropout layers in our model architecture"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "tags": [
          "block:modeling",
          "prev:preprocess_data"
        ],
        "id": "Xsd0iRizNzhV"
      },
      "outputs": [],
      "source": [
        "def build_model(hidden_dim1=int(CONV_DIM1), hidden_dim2=int(CONV_DIM2), DROPOUT=0.5):\n",
        "    model = tf.keras.Sequential([\n",
        "    tf.keras.layers.Conv2D(filters = hidden_dim1, kernel_size = (5,5),padding = 'Same', \n",
        "                 activation ='relu'),\n",
        "    tf.keras.layers.Dropout(DROPOUT),\n",
        "    tf.keras.layers.Conv2D(filters = hidden_dim2, kernel_size = (3,3),padding = 'Same', \n",
        "                 activation ='relu'),\n",
        "    tf.keras.layers.Dropout(DROPOUT),\n",
        "    tf.keras.layers.Conv2D(filters = hidden_dim2, kernel_size = (3,3),padding = 'Same', \n",
        "                 activation ='relu'),\n",
        "    tf.keras.layers.Dropout(DROPOUT),\n",
        "    tf.keras.layers.Flatten(),\n",
        "    tf.keras.layers.Dense(10, activation = \"softmax\")\n",
        "    ])\n",
        "\n",
        "    model.build(input_shape=(None,28,28,1))\n",
        "    \n",
        "    return model"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "tags": [],
        "id": "GlOAJ-qhNzhY"
      },
      "outputs": [],
      "source": [
        "model = build_model()"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "tags": [],
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "rzkTjb46NzhY",
        "outputId": "c46f30a2-0fe1-4c00-b0a8-7c763dc2bdf6"
      },
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "Model: \"sequential\"\n",
            "_________________________________________________________________\n",
            "Layer (type)                 Output Shape              Param #   \n",
            "=================================================================\n",
            "conv2d (Conv2D)              (None, 28, 28, 56)        1456      \n",
            "_________________________________________________________________\n",
            "dropout (Dropout)            (None, 28, 28, 56)        0         \n",
            "_________________________________________________________________\n",
            "conv2d_1 (Conv2D)            (None, 28, 28, 100)       50500     \n",
            "_________________________________________________________________\n",
            "dropout_1 (Dropout)          (None, 28, 28, 100)       0         \n",
            "_________________________________________________________________\n",
            "conv2d_2 (Conv2D)            (None, 28, 28, 100)       90100     \n",
            "_________________________________________________________________\n",
            "dropout_2 (Dropout)          (None, 28, 28, 100)       0         \n",
            "_________________________________________________________________\n",
            "flatten (Flatten)            (None, 78400)             0         \n",
            "_________________________________________________________________\n",
            "dense (Dense)                (None, 10)                784010    \n",
            "=================================================================\n",
            "Total params: 926,066\n",
            "Trainable params: 926,066\n",
            "Non-trainable params: 0\n",
            "_________________________________________________________________\n"
          ]
        }
      ],
      "source": [
        "# display the model summary\n",
        "model.summary()"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "tags": [],
        "id": "b8YIFUQPNzhZ"
      },
      "source": [
        "We are now ready to compile and fit the model."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "tags": [],
        "id": "M8IGPAkjNzhZ"
      },
      "outputs": [],
      "source": [
        "model.compile(optimizers.Adam(learning_rate=float(LR)), \n",
        "              loss=SparseCategoricalCrossentropy(), \n",
        "              metrics=SparseCategoricalAccuracy(name='accuracy'))"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "tags": [],
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "F1SPqWIkNzhZ",
        "outputId": "d66b5c72-a0a3-4c24-957a-d507673be635"
      },
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "Epoch 1/2\n",
            "532/532 [==============================] - 690s 1s/step - loss: 0.2164 - accuracy: 0.9354 - val_loss: 0.0700 - val_accuracy: 0.9791\n",
            "Epoch 2/2\n",
            "532/532 [==============================] - 698s 1s/step - loss: 0.0725 - accuracy: 0.9770 - val_loss: 0.0515 - val_accuracy: 0.9847\n"
          ]
        }
      ],
      "source": [
        "history = model.fit(np.array(X_train), np.array(y_train), \n",
        "                    validation_split=.1, batch_size=int(BATCH_SIZE), epochs=int(EPOCHS))"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "tags": [],
        "id": "y-PR8pdpNzhZ"
      },
      "source": [
        "## Evaluate the model\n",
        "\n",
        "Evaluate the model and print the results"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "tags": [
          "block:"
        ],
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "-t7Z70l8Nzha",
        "outputId": "2244a75f-8d8e-43ae-9326-acd5fb6a1d78"
      },
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "Test_loss: 0.05151399224996567, Test_accuracy: 0.9828571677207947 \n"
          ]
        }
      ],
      "source": [
        "# Evaluate the model and print the results\n",
        "test_loss, test_acc = model.evaluate(np.array(X_test),  np.array(y_test), verbose=0)\n",
        "print(\"Test_loss: {}, Test_accuracy: {} \".format(test_loss,test_acc))"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "tags": [],
        "id": "OTEZfv5GNzha"
      },
      "source": [
        "# Confusion matrix"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "tags": [
          "block:prediction",
          "prev:modeling"
        ],
        "id": "jGo1yht2Nzha"
      },
      "outputs": [],
      "source": [
        "y_pred = np.argmax(model.predict(X_test), axis=-1)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "tags": [
          "block:"
        ],
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 509
        },
        "id": "FX4hVzxENzhb",
        "outputId": "47dc7065-2705-411a-dbef-e2be1235252f"
      },
      "outputs": [
        {
          "output_type": "display_data",
          "data": {
            "text/plain": [
              "<Figure size 504x504 with 1 Axes>"
            ],
            "image/png": "iVBORw0KGgoAAAANSUhEUgAAAewAAAHsCAYAAAAQKp5gAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADh0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uMy4yLjIsIGh0dHA6Ly9tYXRwbG90bGliLm9yZy+WH4yJAAAgAElEQVR4nOzdd3hUVeLG8e9JI5kECGpoQRMkCioqYhQrSBWpKop11d2fioKAXURZEMVd1y6CiLrirr2sBUQXFSmCuiJ2mrSANKWbDCmTnN8fGWKCKROYmZsj7+d58jC5c8s7h5u8uXfuzBhrLSIiIlK3xXgdQERERGqmwhYREXGACltERMQBKmwREREHqLBFREQcoMIWERFxgApbxCPGmAbGmCnGmA3GmBJjjDXGXBGB7awOrntWuNdd1xhjzjDGjAl+pdZiuczgGFljzJgIRhTZa3FeBxDZj40CLvc6xB/MGcDo4O0pwHbPkoiEmQpbxDvtgv9uBzKttTsisRFrbWYk1vtHYYxJstauBozXWUSqo1PiIkHGmC7GmPeMMVuNMQXGmFXGmIfL3X+FMeZ/xpg8Y4zfGLPAGPPnPdYxpdyp1WOMMR8H5/3RGHNpufks0C34bSqwPbhMZvl17LHu3eudUm5at+A2fglmXmeMed8Yc3a5eSo9JW6M6WuMmW2M2WmMyTfGfGeMudkYE1tunjHlttvJGPN28PHnGGNuqcXYXlFuPecbY/4THJelxphexpgkY8wTxpgdla3bGPMXY8xcY8xGY0xhMPM8Y8x55eaZxW9H1wCrgttbXclj6WqMmWGM8QN/q+yUuDHmH8HvS4wxJwenNTPG7P6/ejfUxy8SFtZafelrv/8C/gyUAHaPr9XB+++r5L7dX/eVW8+UctO37zFfCXBkcL6q1pVZfh17ZNw9z5Tg9xnArirW83i55VYHp80qN+3aajK8Um6+MdU8Hgv0DHF8ryi3zJY91rELmFHduoGXq8nbKzjPrCruX13JY9la7vYjwXHf/f2Y4Pz1gEXBad8B8cAb5ZZv7vV+q6/960tH2LLfM8akAA9TekrUD5wP1AcOB8YbY1oBNwdn/w44FGgZvA1wc3CePc0CDgKu3r0p4FwAa60BZgen51hrTfBrdS2iZwOJwdsnUFowGcDFwCdVLWSMqU/pHyAA64BjgSbAzOC0gcaYMypZdAmQDpxZbtp5lcxXk7VAc+C64PeJQAdKH88JlBbinuueHMyZSmlxtgmuB+AaAGvtGcBd5ZZpGRzTzEoybAKOofT/+bHKQlprCyi9xqAYaAu8Q/D/DxhqrV1f4yMVCSMVtgicAjQM3n7CWvu6tTbXWvujtfZBSk9d7/5ZedBauypYrA8Gp8UAXStZ7+3W2i3A8+WmHRzG3Dnlbo8EhlBaZNOstS9Xs9wplBYVwFPW2m+ttT8DY8vN06OS5e6y1q631s4Afg5O25vHM95auwH4qNy0t621X1prFwAbK1n3RkqPkJcB+ZT+8bD7/sP3IsNfrbXfBf+fV1Y1k7X2C+AfwW97Bv9901r7wl5sU2SfqLBFIK3c7aWV3H9Qudtry93+qYp17PZj8N/8ctPq1S5aqfLPK+8WLLdxlJ5SPgd4CPgvsMkYc2U1q9vXxwO/Paa9eTy7/9AoPy5ryt0uLL9uY0xDSh/XOUBjYM+xSKT2vqt5ljITKH06Y7cn9mJ7IvtMhS0Cv5S73bqS+zeXu92iitvl5wHAWhsI/lvbz7At2H3DGLO7jDIrm9FaeyelBXwqpc8TfwYkAY8ZY6p6FchePR4gUH7TVaw7FIEQp+12Er9l+zuQHHxK4ctK5g01V37Ns5R5mIq/Kx80xiTUYnmRsFBhi8B8YPdLqq4xxpxrjEk2xhxqjLkR+JDfjrBuCl5RnAHcGJxWEpwnXMof6Z5pjImh9JR3BcaYo40xoyg9JfwD8DrwVfDuJH477b2nT4Hc4O2rgutJA+4sN8+MfcgfbuXLMQ+wxphLgPaVzLut3O22+7phY8wFlF7TAKVnMIqBo6l4NbpIVKiwZb9nrc0FbqD06CyZ0iuBc4EVwDBr7QpKj7Kg9EKlVZReeX1McNrDwXnC5T/8dqT4JrATuKiS+Q6k9Hnnryi9gjuX0qu/AT631m6rZBmstTuB24PftgC+pfQ56d0vM3vdWvvxPj6GcJrPb0V8N6UXBj4DVHbR1xflbk8Nvvzq+Urmq5ExpjHwePDb96y1NwGPBr+/1RiTvTfrFdlbKmwRwFr7LKWF9T6l5VBIaSm/Gbz/ZuBKSk/D7qL0lOpC4KrgfeHM8gNwGaXPGRcEt9mxklmXU3r19A+UniEoCGaeDJxdyfzlt/E4pc8Jz6W06AsofQnTbVT+x4Fnghfu9ad0vPMpfbz9KX38e877KaVnI9ZS8XnnvTGJ0qcbcgleiU7pu9OtoPRNp54zxuzVNQkie8PU/uk1ERERiTYdYYuIiDhAhS0i+2SPt/Ws7OsKrzOK/BGosEVERByg57BFREQcoCNsERERBzj3ediN/+9Vp04JrHlyoNcRRPYbrp0wNPoEbtlDYlzVn8uuI2wREREHqLBFREQcoMIWERFxgApbRETEASpsERERB6iwRUREHKDCFhERcYAKW0RExAEqbBEREQeosEVERBygwhYREXGACltERMQBKmwREREHqLBFREQcoMIWERFxwH5V2C0bp7Bm0gAmXtmhbNq5HQ7hy3/0ZtXEc3nuulNJTU4IaTmv7Ni+neuHDaFDdjt6duvM9GlTvY5ULdfyvvTC81w08Fyy27Vl1MgRXscJiWtj7FrekbfdTLczTuPUDu3p1/tM/vP6a15HqpZr46u8oYuL2pbqgPsubc/Xq7aWfd+6eQMeuOx4Ln50Lt/lbOeBy47nvkvbM+jJz6pdzkv33jOW+Ph4Pp49jyVLFjN08CAOb9OGrKzDvI5WKdfypjVuzFWDBjN/3lwK8gu8jhMS18bYtbx/uWoQY+6+l4SEBFatXMGVf76MNkccwZFHtfU6WqVcG1/lDd1+c4R99okHs8NfxNzFP5dNG3BSBv/9ej2fLdtMXkGA+976nt7t00lOjKt2Oa/4/X4+/GAGQ4YOx5ecTPvjs+nUuQvT3nnb62iVci0vQLfuPejStRupDVO9jhIS18bYtbwAWVmHkZBQeubNGIMxhrVr13icqnKuja/y1k7UCtsYc4Qx5l5jzNvGmJnBf+81xhwR6W2nJMZxW/+2/PWVrytMb928AYt+2lH2/epf8igKlNCqSf1ql/NKTs5q4uJiycxsWTatdes2rFi+3MNUVXMtr4tcG2PX8u427u4xnJR9LGf3PYuD0tI4vWMnryNVyrXxVd7aiUphG2MuAj4FWgBzgBeB2UA6MN8Yc0Ektz/inLa8+MkqNmzbVWF6cmIcO/1FFabt3FVESvAIu6rlvLLL7yc5OaXCtJSU+vj9eR4lqp5reV3k2hi7lne3O0aNYd7nC3n2Xy/QtVt34uN/f61LXeDa+Cpv7UTrCPteoLe19jJr7YPW2qettQ9Zay8H+gD3VbewMeZqY8wCY8yCXUs+rNWG2x6cSscjmjBpxrLf3ZeXH6B+UsWn8esnxZObH6h2Oa8k+Xzk5eVWmJabl4vPl+xRouq5ltdFro2xa3nLi42N5bj22WzauJHXXnnJ6ziVcm18lbd2onXRWRqwsIr7vgIOqm5ha+1kYDJA4/971dZmw6e0TuPgg5L56v7eACTXiyMmxvBh8+7M/H4jRx3823OVGQclkxAXw4pNv3LJaS2rXK7b2A9qEyFsMjIyCQSKyclZTUZGJgDLli6hVVaWJ3lq4lpeF7k2xq7lrUxxcXGdfQ7btfFV3tqJ1hH2B8A/jTGtyk8Mfv9U8P6I+PeclXQYMZ0uYz6gy5gPeG72Sj78dgMXPDSHNz7Locexzelw2EH4EmK57ey2vLtwHXn5gWqX84rP56Nr9+5MHP8Yfr+frxZ+yayZH9GnX3/PMlXHtbwAgUCAgoICiktKKC4ppqCggEAg4HWsKrk2xq7l3bplC+9Pfxe/P4/i4mLmz5vLe++9S4eTTvY6WqVcG1/lrR1jba0OWPduI8Y0AiYC5wJFwE6gAaVH+P8Bhlhrt4WyrtoeYe/pln5H0bJxCoOf/hwofR32nQOOplFKPeYs2sTwZ79ge15hjcuFas2TA/cl7u/s2L6d0aNG8umn80ltmMrwG26iV5++Yd1GOLmW94kJ45k08fEK064ZfB3XDhnqUaKauTbGkcwb7l9nW7du5ZYbh7F06RJsSQnNmqdz0SV/YsB54fm5NiYsq6lA+0NkRTpvYhxV7hVRKeyyjRnjAw4HUoBcYJm11l+bdexrYUdbuAtbRKoWxV9nYRGJwha3VVfYUX3jlGA5143XSImIiDhkv3njFBEREZepsEVERBygwhYREXGACltERMQBKmwREREHqLBFREQcoMIWERFxgApbRETEASpsERERB6iwRUREHKDCFhERcYAKW0RExAEqbBEREQeosEVERBygwhYREXGAsY594nt+AKcCN+oxzusItbJtxh1eRxAR2W8lxmGquk9H2CIiIg5QYYuIiDhAhS0iIuIAFbaIiIgDVNgiIiIOUGGLiIg4QIUtIiLiABW2iIiIA1TYIiIiDlBhi4iIOECFLSIi4gAVtoiIiANU2CIiIg5QYYuIiDhAhS0iIuKA/b6wd2zfzvXDhtAhux09u3Vm+rSpXkcq0yq9Edvev41/3t6vbNpBDX1MuaM/G9+5ifVv38izI/uX3df8oPq8evf5rHvrRpa/MpQr+7b3InYFdXl8K/PSC89z0cBzyW7XllEjR3gdJySujbFLebU/RJ7yhi4ualuqo+69Zyzx8fF8PHseS5YsZujgQRzepg1ZWYd5HY1HhvfkyyXrK0x7+a4BfLl0A4df9Dj+/CKOaplWdt8/b+/Hdyt/5uIxb3BExkG8/9ClLFu7hTlf50Q7epm6PL6VSWvcmKsGDWb+vLkU5Bd4HSckro2xS3m1P0Se8oZuvz7C9vv9fPjBDIYMHY4vOZn2x2fTqXMXpr3zttfROL/zkezIzefjr1aXTeua3ZIWjRtw+5MfsTOvgEBxCd8s3wRAcmI8nY7L5L7n5xEoLuG7lT/z5pwlXH7WsR49gro9vlXp1r0HXbp2I7VhqtdRQuLaGLuWV/tDZClv7ezXhZ2Ts5q4uFgyM1uWTWvdug0rli/3MBXU9yUw6oqO3DbxwwrTTzwinWVrt/D0bX356c0b+GTinzntmEMAMMYE//1tfmPgyMw0vFJXx/ePxLUxdi2va1wbX+WtnTpR2MaYWGPMX6O93V1+P8nJKRWmpaTUx+/Pi3aUCkb/uRPPvfcN6zb/WmF6eloDup/Qitlf55B53qM8+trnvHbP+RzYIIncXYXM/24tt//pNOrFx9LusKacfXobfInxHj2Kuju+fySujbFreV3j2vgqb+3UicKm9Ln00VXdaYy52hizwBiz4JmnJodto0k+H3l5uRWm5ebl4vMlh20btXVMqyZ0Pr4lj73++e/uyy8oYvWG7Tz33jcEikt47eNF/PTzTk5uezAAf773LTKapvLjK0N57PqevPzh96z7ZWe0H0KZuji+fzSujbFreV3j2vgqb+1E7aIzY8w/9zaHtXYyMBkgP4ANV6aMjEwCgWJyclaTkZEJwLKlS2iVlRWuTdRax3aHkNGkIcteHgpASlICsTGGNplpPPnWAnqdXPHCBmt/G441m3Yy4I5Xy76fckd/Fuxx0Vo01cXx/aNxbYxdy+sa18ZXeWsnmkfYFwO7gHWVfP0UxRxlfD4fXbt3Z+L4x/D7/Xy18EtmzfyIPv3617xwhDwz7SuOunQiJ131NCdd9TRPT13I+58tp9+tL/HOJ0tJrZ/IJT2OJibGcE7HNqSnNeDT79cC0PqQA0lJSiA+LoYLu7Wla/ahPPba/zx7LHVxfGsSCAQoKCiguKSE4pJiCgoKCAQCXseqkmtj7Fpe7Q+Rpby1Y8ofoUV0Q8Z8AdxtrX2nkvsSAb+1tsY/IMJ5hA2lr6kbPWokn346n9SGqQy/4SZ69ekbtvU36jFun5a/4/LTadW8EX/5W+mwnXr0wTwyvCeZzVJZumYLt038gHnflRb2dQNO4NZLTsVXL55vlm/ilgkfsHDZhlptb9uMO/Yp754iPb7h9sSE8Uya+HiFadcMvo5rhwz1KFHNXBtjl/Jqf4g85a0oMQ5T1X3RLOwhwDpr7VuV3BcL3Gmtvaum9YS7sCNtXws72sJd2CIiErrqCjtqz2FbaydUc18xUGNZi4iI7K/qylXiIiIiUg0VtoiIiANU2CIiIg5QYYuIiDhAhS0iIuIAFbaIiIgDVNgiIiIOUGGLiIg4QIUtIiLiABW2iIiIA1TYIiIiDlBhi4iIOECFLSIi4gAVtoiIiANU2CIiIg4w1lqvM9RKfgCnAjs2vGRc86rXEWplzZMDvY5QK67tD8Z4neCPraTEsR0CMI7tFI7FJTGOKhPrCFtERMQBKmwREREHqLBFREQcoMIWERFxgApbRETEASpsERERB6iwRUREHKDCFhERcYAKW0RExAEqbBEREQeosEVERBygwhYREXGACltERMQBKmwREREHqLBFREQcsN8X9o7t27l+2BA6ZLejZ7fOTJ821etIVSosLGTMqJGc1b0zp5x4HAMH9OeTubO9jlWmZeMU1kwawMQrO5RNO7fDIXz5j96smnguz113KqnJCWX3vXnLGayZNIBVE85h1YRzmD+upxexK3jphee5aOC5ZLdry6iRI7yOE5KRt91MtzNO49QO7enX+0z+8/prXkeqlks/c+BeXoD333uXc/v14uQTj6PvWd1Z+OUCryNVSftv6OKitqU66t57xhIfH8/Hs+exZMlihg4exOFt2pCVdZjX0X6nOBCgSdNmPD3l3zRr1pxP5szm1puu57U3p5Ke3sLreNx3aXu+XrW17PvWzRvwwGXHc/Gjc/kuZzsPXHY8913ankFPflY2z+0vLOSFuau8iFuptMaNuWrQYObPm0tBfoHXcULyl6sGMebue0lISGDVyhVc+efLaHPEERx5VFuvo1XKpZ85cC/vZ/Pn8ejDD3Lf/Q/R9uhj2PzLL15Hqpb239Dt10fYfr+fDz+YwZChw/ElJ9P++Gw6de7CtHfe9jpapZJ8Pq4dMpT09BbExMTQ8YzOpKe3YPGiH7yOxtknHswOfxFzF/9cNm3ASRn89+v1fLZsM3kFAe5763t6t08nObHu/p3YrXsPunTtRmrDVK+jhCwr6zASEkrPXBhjMMawdu0aj1NVzrWfOdfyAjwxcTxXXzOYY45tR0xMDI2bNKFxkyZex6qS9t/Q7deFnZOzmri4WDIzW5ZNa926DSuWL/cwVei2bN5MTs5qWrXK8jRHSmIct/Vvy19f+brC9NbNG7Dopx1l36/+JY+iQAmtmtQvm3bHgKNZ/Eh/po3owimt06KW+Y9m3N1jOCn7WM7uexYHpaVxesdOXkeqlGs/c67lLS4uZtEPP7Bt61b69erBmV078fdxY8nPz/c6WrW0/4YmaoVtjDnEGHOOMebwSu67KFo5ytvl95OcnFJhWkpKffz+PC/i1EpRUREjR9xM3/7n0PLQVp5mGXFOW178ZBUbtu2qMD05MY6d/qIK03buKiIleIR99+vfcsKI6Rx781T+PWcFzw87jcy05Kjl/iO5Y9QY5n2+kGf/9QJdu3UnPj6h5oU84NrPnGt5t2zZTCBQxIcf/Jdnnnuel19/iyVLFvP05Ce8jlYt7b+hiUphG2N6At8DY4CvjTETjTGx5WZ5soblrzbGLDDGLHjmqclhy5Xk85GXl1thWm5eLj5f3S6NkpIS7rz9VuLi4xkxcpSnWdoenErHI5owacay392Xlx+gflLF09/1k+LJzQ8AsHDVVvLyAxQGSnhlfg7/+3EzXY9uFpXcf0SxsbEc1z6bTRs38torL3kdp1Ku/cy5ljexXiIAF158KWlpjWnUqBGXXnYFn8yd43Gymmn/rVm0nky8F7jIWvuuMaYJ8DzwtjHmXGttIWCqW9haOxmYDJAfwIYrVEZGJoFAMTk5q8nIyARg2dIltMry9hRzday1jPnrHWzZspnHn3iK+Ph4T/Oc0jqNgw9K5qv7ewOQXC+OmBjDh827M/P7jRx18G/PBWcclExCXAwrNv1a6bospc9hyb4pLi6us88BuvYz51reBg0b0qRJ0wo/R679TGn/rVq0Tom3sta+C2Ct3QScBeQC040xvihl+B2fz0fX7t2ZOP4x/H4/Xy38klkzP6JPv/5eRarRuLGjWbVyBY9NmERiYqLXcfj3nJV0GDGdLmM+oMuYD3hu9ko+/HYDFzw0hzc+y6HHsc3pcNhB+BJiue3stry7cB15+QEaJMXT+agm1IuLITbGMKDDIZx0eBozv9/g6eMJBAIUFBRQXFJCcUkxBQUFBAIBTzNVZ+uWLbw//V38/jyKi4uZP28u7733Lh1OOtnraJVy7WfOtbwA/c4+l5dffJ6tW7awc8cOXvj3c5ze8QyvY1VK+2/tGGvDdsBa9UaMWQ2cbq1dW26aAZ4B2gDtrLUhFXc4j7Ch9DV1o0eN5NNP55PaMJXhN9xErz59w7b+cA7v+vXr6NWjCwkJCcTG/nZy5M7Rd9G7T7+wbCPjmlf3aflb+h1Fy8YpDH76c6D0ddh3DjiaRin1mLNoE8Of/YLteYUcmFKPF68/ncOa1ae4xPLjhl+5763vmb1oU622t+bJgfuUd09PTBjPpImPV5h2zeDruHbI0LCsP9w/blu3buWWG4exdOkSbEkJzZqnc9Elf2LAeeEZl0gcnEX6Zy7cIpm3pCT8v3+Lioq4/757eW/6NOol1KP7mT25/sZbqFevXljWH84j9kjvvxD+fTjS+29iXNVnnKNV2E8Da6y1Yyu5bxJwtbU2pKP9cBd2pEVheMNqXws72sJd2JHm2v7g2NlU50SisCPNtVPsjsWttrCj9Rz24Kq2Za29xhhzb5RyiIiIOCkqhR28sKywmvvr5hUGIiIidcR+/cYpIiIirlBhi4iIOECFLSIi4gAVtoiIiANU2CIiIg5QYYuIiDhAhS0iIuIAFbaIiIgDVNgiIiIOUGGLiIg4QIUtIiLiABW2iIiIA1TYIiIiDlBhi4iIOMBY69YHqOcHcCuwRFSjE67zOkKtbPvica8jSB3i2K9fAIzxOsEfW2IcVY6wjrBFREQcoMIWERFxgApbRETEASpsERERB6iwRUREHKDCFhERcYAKW0RExAEqbBEREQeosEVERBygwhYREXGACltERMQBKmwREREHqLBFREQcoMIWERFxgApbRETEASpsERERB+z3hb1j+3auHzaEDtnt6NmtM9OnTfU6UrWUd9/996nhbPvsYX6Z9yC/zHuQb94cVXbfBT2zWTp9LJvnP8irD11FowY+ABLi43hi9MUsnT6Wnz95gM9eHkGPU4/06iFUUBfHuDrKGzmFhYWMGTWSs7p35pQTj2PggP58Mne217Gq9dILz3PRwHPJbteWUSNHeB2nRl7mjYvq1uqge+8ZS3x8PB/PnseSJYsZOngQh7dpQ1bWYV5Hq5TyhscN973KlDc/rTDtiEObMv7OCzln2BN8vXgtE0ZdzKMjL+CyEc8SFxvDTxu30/3/HmHtxm30PO0onr/vL2Sffy9rNmz16FGUqqtjXBXljZziQIAmTZvx9JR/06xZcz6ZM5tbb7qe196cSnp6C6/jVSqtcWOuGjSY+fPmUpBf4HWcGnmZd78+wvb7/Xz4wQyGDB2OLzmZ9sdn06lzF6a987bX0SqlvJF1Ya8TmD7ne+YtXEHerkLumjiN/l2OJcVXD39+IeOenM6aDVux1vLe3O9ZvW4L7Y88xNPMro2x8kZWks/HtUOGkp7egpiYGDqe0Zn09BYsXvSD19Gq1K17D7p07UZqw1Svo4TEy7xRK2xjzHHGmPOMMT5jTKwx5jpjzMPGmN7RyrCnnJzVxMXFkpnZsmxa69ZtWLF8uVeRqqW84TN2aD/Wzvw7M5+9gdOPLz1SOqJVM75b9lPZPKt+2kxhUTGHZTT+3fKND6jPYRmNWbRiQ9QyV6Yuj3FllDe6tmzeTE7Oalq1yvI6ioRBVE6JG2P+D7gHsMAI4D/AwcHtv2yMGW6t/Wc0spS3y+8nOTmlwrSUlPr4/XnRjhIS5Q2POx99i8UrN1JYVMz5PY/njUcH0eHCv5OSVI8dufkV5t2Zu4sUX2KFaXFxMTx77+U8P/Vzlq3eFM3ov1NXx7gqyhs9RUVFjBxxM337n0PLQ1t5HUfCIFpH2LcAnYDOQHtglrX2WmvtVcB5wPDqFjbGXG2MWWCMWfDMU5PDFirJ5yMvL7fCtNy8XHy+5LBtI5yUNzy++D6HXH8BhUUBXpj6OZ9+vZKepx1F7q4CGiRXLOf6yYnk+n8rcWMM/7zncgqLirnhvlejHf136uoYV0V5o6OkpIQ7b7+VuPh4RowcVfMC4oRoFXYza+0ya+1SYBdQ/mqfD4CM6ha21k621mZba7P/76qrwxYqIyOTQKCYnJzVZdOWLV1Cq6y6efpIeSPDYjEGFq/YwNGHp5dNz0w/kHoJcfyY83PZtEmjL6HxAfW56OanCQRKvIhbgStjvJvyRp61ljF/vYMtWzbz4MPjiY+P9zqShEm0CjvPGLN7r5lirbXl7ksCPPnN5/P56Nq9OxPHP4bf7+erhV8ya+ZH9OnX34s4NVLefdcwJYluJx9BvYQ4YmNjuPCsbE5rn8WMeYt5efoX9OrYllOPa4UvMYG/Xtubt2d+Q66/9ErQx+64kDYtmzBg+CTyC4o8ewzl1cUxro7yRt64saNZtXIFj02YRGJiYs0LeCwQCFBQUEBxSQnFJcUUFBQQCAS8jlUlL/Oait0ZoY0Y82/gXmvt4kruuwC41lp7Rijryg8Q1sA7tm9n9KiRfPrpfFIbpjL8hpvo1advODcRVspbUaMTrqvV/Ac1SuGt8ddyeGYTiktKWLZqE3dNfJeZny8BSl+HffewfhyQmszMz5cyaPTzbNvp55BmjVg6/W7yC4oIFP/29+XQe17i5fcWhLz9bV88XnPhZY4AACAASURBVKu8odA+EVmRzBvuX7/r16+jV48uJCQkEBv72yVKd46+i959+oVlG8aEZTVlnpgwnkkTK/5cXDP4Oq4dMjS8GwqTSOdNjKPKEY5KYVfHGJMGWGvt5lDmD3dhi9tqW9hei0Rhi7s8/vW7V8Jd2FJRdYXt+RunWGt/8TqDiIhIXbdfv3GKiIiIK1TYIiIiDlBhi4iIOECFLSIi4gAVtoiIiANU2CIiIg5QYYuIiDhAhS0iIuIAFbaIiIgDVNgiIiIOUGGLiIg4QIUtIiLiABW2iIiIA1TYIiIiDvD887BrS5+HLS47bPjbXkeolR8f7e91hD88x34FO/d52CWODbAvvuoR1hG2iIhHHOsS8ZgKW0RExAEqbBEREQeosEVERBygwhYREXGACltERMQBKmwREREHqLBFREQcoMIWERFxgApbRETEASpsERERB6iwRUREHKDCFhERcYAKW0RExAEqbBEREQfEVXWHMebfUPNnT1trLwtrIhEREfmd6o6wlwMrQvhy2o7t27l+2BA6ZLejZ7fOTJ821etI1VLeyKtrmR+9vD0L7j2TRQ/0YvZfu3LhKYeU3denfXNmjurC4gd789GdXTjzmKZl9yXExTB6QFsWjDuT7+4/i3EXHENcjPHiIVRQ18a3Oi+98DwXDTyX7HZtGTVyhNdxalRYWMiYUSM5q3tnTjnxOAYO6M8nc2d7HataLu0PAFde8Sc6tD+GU05ozykntOfsPj2jtu0qj7CttXdFLYWH7r1nLPHx8Xw8ex5Llixm6OBBHN6mDVlZh3kdrVLKG3l1LfOEGT9yywtfUxgooVWTFF69/lR+WLuDX3YW8Ojlx/N/T37OrEU/0+WoJky6MpuTR33AltxCBvc4jGMOSaXbuJnExBievaYDw846nIfeXerJ49itro1vddIaN+aqQYOZP28uBfkFXsepUXEgQJOmzXh6yr9p1qw5n8yZza03Xc9rb04lPb2F1/Eq5dL+sNttI0dx7nnnR327IT+HbYzpbox5xhgzNfh9tjGmS+SiRZ7f7+fDD2YwZOhwfMnJtD8+m06duzDtnbe9jlYp5Y28uph52YZfKQyUAGBt6VdGWjJNGyWxc1cRsxb9DMDMHzbhLygmIy0ZgO5tm/LPWSvZ7i9ia24hz85ayQUnZ3j2OKBujm91unXvQZeu3UhtmOp1lJAk+XxcO2Qo6ektiImJoeMZnUlPb8HiRT94Ha1Sru0PXgupsI0xQ4EngB+BjsHJu4B79mXjxpgFxpgD9mUd+yInZzVxcbFkZrYsm9a6dRtWLF/uVaRqKW/k1dXM4y44hmUP92b26K78vCOfmT9s4tucbSzf+Cvdj25KjIEzj2lKYaCExet2li1nyp8BN4bmjZKon1jlibWIq6vj+0e1ZfNmcnJW06pVltdRKuXq/jD+0YfofNpJXHHpRSz43+dR226oP7nXA12ttauNMbcFpy0BWoeysDHmX1XcdSQwyRiT78XFa7v8fpKTUypMS0mpj9+fF+0oIVHeyKurme945VtGvfotxx96ACcfdhCFRSWUWHj987WM//Px1IuLoai4hGueXsCuwmIAZi3axF/OOJT5yzYTG2P4yxmHApCUEMuv+QFPHkddHd8/oqKiIkaOuJm+/c+h5aGtvI5TKRf3h+E33syhrVoRH5/A+++9y/DrruXl19/i4EMOqXnhfRTqKfH6wNrg7d1XjscDhSEufz6Qwe8vZCsGcqjh4jVjzNXBo/EFzzw1OcRN1izJ5yMvL7fCtNy8XHy+5LBtI5yUN/LqcuYSC1+s2ErT1ET+1LElp7VO446zj2LgI/M4dPhUzn94Hv+4pB1HtmgAwPj/LuOHn3bw39vP4M2bTue/32ygMFDCL79691xsXR7fP5KSkhLuvP1W4uLjGTFylNdxquTi/nD0MceSnJxCQkIC/fqfQ7vj2kftwr5QC3sOsOclksOAj0Nc/hggn9Ij6qestXcFL2rLBe6v6QI3a+1ka222tTb7/666OsRN1iwjI5NAoJicnNVl05YtXUKrrLp5+kh5I8+FzHExMWQc5OOoFg34fPkWvl2zHWvhmzXb+Xr1Nk5vnQZAflEJo179jhPumMFpoz9kW14h3wXn9YoL4+s6ay1j/noHW7Zs5sGHxxMfH+91pCr9IfYHY7BR+qEKtbCHAucYY1YD9Y0xS4GBwI2hLGyt/dFaeybwFvCxMeZmY0wcIbzOO5J8Ph9du3dn4vjH8Pv9fLXwS2bN/Ig+/fp7GatKyht5dS3zgSkJ9Ds+HV+9WGIMdDoijf7Z6cxbuplvcrZzYtYBZUfUR7VoyImtDix7Drtpw0SaNEwE4LjMRgw/qzUPvbvEk8exW10b35oEAgEKCgooLimhuKSYgoICAgFvnk4I1bixo1m1cgWPTZhEYmKi13Gq5dr+8OvOnaWvGAjuB9OnTWXhlws49bTTo7J9E+pfBsYYA5xA6anttcD/rLUltd6gMQ2AsUC34LpaWWt/DnX5/EB4S37H9u2MHjWSTz+dT2rDVIbfcBO9+vQN5ybCSnkjL5KZDxteu6tfD0hJ4MkrT+CI9IbEGFi3dRf/nLWSl+bnAHB5p5Zc2flQDqqfyJbcAv41ZxWTPyp9hqlD1oE8fFl7DqqfwPpt+Tzy3lLe+uKnWm3/x0fD/4vTpX3iiQnjmTTx8QrTrhl8HdcOGRqW9Yf7wGz9+nX06tGFhIQEYmN/u0TpztF30btPv7Bsw4T5pfyR3h9KwjjIW7duZei1V7N61UpiYmNp2fJQBl83jJNOOTVs2/DFVz3CtSnsWOAkoDmwHvjMWlu8t6GMMe2ATsCT1tr8UJcLd2GLRFNtC9trkShs+Y2XT0/srXAXdqSFs7CjobrCDukqcWPMMZSezq4HrANaAPnGmHOstd/sTShr7dfA13uzrIiIyP4m1Oew/wlMAFpYa08E0oHHg9NFREQkwkIt7MOBR2zw/Hnw30eBuvvecSIiIn8goRb2dGDPKxb6Au+GN46IiIhUJtSP14wFXjbGfEnpFeIHA8cDbl1BIyIi4qjqLjrb881cvy93exHw3/DHERERkcrs9x+vKSIi4oKQP7bHGJNA6Yd9HASUvU7MWjszArlERESknFBfh30a8Bqlr8NuAOzktw8EOTRi6URERAQI/Srxh4F/WGsPAH4N/ns3MDFiyURERKRMbV6H/ege0/4O3BDeOCIiIlKZUAt7B6WnwgE2GGOOBBoBKVUvIiIiIuESamH/B+gVvP1PSj8H+0vg9UiEEhERkYpCuujMWnt9udsPGGM+p/ToWq/FFhERiYKQX9ZVnrV2briDiIiISNWqe2vSuVDzZ09bazuGNZGIiIj8jrFVfLi3MebyUFZgrX0urIlqkB+o+Y8I2X+49uH0MVV/Nn2d1OWhOV5HqJWZN+r4QSpy7FcESfFU+UuiurcmjWoRi4iISNVCvUpcREREPKTCFhERcYAKW0RExAEqbBEREQeEVNjGmHrGmHHGmJXGmB3BaT2MMddFNp6IiIhA7T6tqy1wCb+9NvsH4NpIhBIREZGKQn2ns3OALGttnjGmBMBau84Ykx65aCIiIrJbqEfYhexR7saYNGBL2BOJiIjI74Ra2K8BzxljWgIYY5oBjwMvRyqYiIiI/CbUwh4JrAK+A1KBH4H1wF0RyiUiIiLlhPrxmoXADcANwVPhm21Vb0IuIiIiYRdSYRtjDt1jUn0T/BADa+3KcIcSERGRikK9Snw5pS/nKv8pIruPsGPDmkhERER+J9RT4hWe6zbGNAVGA3MjEUpEREQq2qu3JrXWbgSuB/4W3jjRt2P7dq4fNoQO2e3o2a0z06dN9TpStZQ3OnJyVtOh/THccdstXkepUV0b49G9W/PO4A58MPwUXr4ym77HNAUg80Afz1x2HO8PO5n3h53MowOPJvNAX9ly7Q9pyPgLj2HG8FN4Y9CJXsX/nbo2vjVxLe9LLzzPRQPPJbtdW0aNHOF1nBqNvO1mup1xGqd2aE+/3mfyn9dfi9q2Qz0lXpnWgK/Gueq4e+8ZS3x8PB/PnseSJYsZOngQh7dpQ1bWYV5Hq5TyRsff7xnLUW2P9jpGSOraGP/rs7Xc+/4yiootGQck8fiFx7JsUy7rtu/ijrcWsXFnATEGBhzXnLF923DZlIUA7Cos4d1vN/JhfAyXnXSIJ9krU9fGtyau5U1r3JirBg1m/ry5FOQXeB2nRn+5ahBj7r6XhIQEVq1cwZV/vow2RxzBkUe1jfi2Q30v8bnGmDnlvhYAnwMPRTZeZPn9fj78YAZDhg7Hl5xM++Oz6dS5C9PeedvraJVS3uh4f/q71G/QgBM7nOR1lBrVxTFetcVPUXHpJS4WsFjSUxPJLShm487SX8gGKLaWFo2SypZbvPFX3l/0M+u253uQunJ1cXyr41pegG7de9ClazdSG6Z6HSUkWVmHkZCQAIAxBmMMa9euicq2Qz3CfnqP7/OAb6y1P4Y5T1Tl5KwmLi6WzMyWZdNat27Dgi++8DBV1ZQ38nJzc3liwmNMfuY53nwjeqe69lZdHeObu2fRq20TEuNjWbrpVz5dubXsvv8OO4WkhFhiDDz9SY6HKWtWV8e3Kq7lddW4u8cw9e03yc/Pp80RR3J6x05R2W6NhW2MiQW6AFdba8NyviL4jmm9KP1D+31r7fJwrLe2dvn9JCenVJiWklIfvz/Pizg1Ut7Imzj+Uc4+9zyaNG3qdZSQ1NUxfuCD5Tz04XLaNm9A+0NSKSz+7W0bznxsPonxMfQ6qknZEXddVVfHtyqu5XXVHaPGMGLkKL795isWfPE/4uMTorLdGk+JW2uLgR5Ayd5uxBizuNztTsA3QB9KS/srY0yXGpa/2hizwBiz4JmnJu9tjN9J8vnIy8utMC03LxefLzls2wgn5Y2spUsW8/lnn3LpZZd7HSVkdXmMSyx8u24nafUTOLddswr35ReV8ObXGxjVuzWNfPEeJaxZXR7fyriW12WxsbEc1z6bTRs38torL0Vlm6GeEn8YuMsYM9paW7QX22lR7vY9wHXW2n8BGGMuCU47paqFrbWTgckA+QHC9g5rGRmZBALF5OSsJiMjE4BlS5fQKisrXJsIK+WNrAVf/I/169dxVrfSvx/9fj8lJcWsPH8FL732H4/TVc6FMY6NMaSnJv1ueoyBxLgY0lIS2Obfm18rkefC+JbnWt4/guLi4qg9h13tEbYx5qLgzaHALcCvxpi1xpg1u79C3E75km0NlP9z5GWgTaiBw8nn89G1e3cmjn8Mv9/PVwu/ZNbMj+jTr78XcWqkvJF17nkDmfreDF5+401efuNNzht4Aad17MSEJ/e8hKPuqGtj3MgXT7c2aSTFxxBjoENmI7q3acyCNds4ISOVwxsnE2PAlxDLsC6t2FkQYPUWP1D6/FhCrCEuxlS47aW6Nr41cS0vQCAQoKCggOKSEopLiikoKCAQCHgdq1Jbt2zh/env4vfnUVxczPx5c3nvvXfpcNLJUdm+qe4twY0xO621DYKnsStlrZ1d40aM2QUMpvRn8m/AodbavOB99YCfrbUNQwkcziNsKH3N4uhRI/n00/mkNkxl+A030atP33BuIqyUt6KSCL6l/aQJ41m7Zg3j7rs/bOuMMeEvoEiOcZeH5tRq/tSkeMadfQRZaSnEGNi4s4DXvlzHO99upHPrg7j6tEzS6tejIFDM4g2/8sSc1az4pfT51eMObsiEi46tsL6Fa7Zz3cvfhrz9mTd2rFXeUOhnLrKemDCeSRMfrzDtmsHXce2QoWFZfzh/RWzdupVbbhzG0qVLsCUlNGuezkWX/IkB5w0M2zaS4qnyl0RNhf2rtbb+vgYwxsyi4lH2rdbaL4L39QDusdaG9E4J4S5scVskCzsSIlHYkVTbwvZaJApb3ObYr4hqC7um57BjjTGdoeoVWGtn1hTAWntGNXd/TunFZyIiIlKFmgq7HvAMVRe2Bfb8JK9asdbu2JflRURE9gc1FXaetXafCllERET23V59+IeIiIhEV02F7dYVMiIiIn9Q1RZ2OK4QFxERkX2nU+IiIiIOUGGLiIg4QIUtIiLiABW2iIiIA1TYIiIiDlBhi4iIOECFLSIi4gAVtoiIiANU2CIiIg5QYYuIiDjAWMc+3Ts/gFuBRSRqWg5+w+sItbJq4gCvI9SaY5WBcewTMRLjqv4MDx1hi4iIOECFLSIi4gAVtoiIiANU2CIiIg5QYYuIiDhAhS0iIuIAFbaIiIgDVNgiIiIOUGGLiIg4QIUtIiLiABW2iIiIA1TYIiIiDlBhi4iIOECFLSIi4gAVtoiIiANU2CIiIg7Y7wt7x/btXD9sCB2y29GzW2emT5vqdaRqKW/kuZbZpbwvvfA8Fw08l+x2bRk1coTXcQB4/C8n8PX9vVj2aD8+ubsHF5+WWXbfxadlMv+eM1n+WH9eHHYqTRomlt3XICmeR6/I5rsHevPdA725qe8RHqT/PZf2h8LCQsaMGslZ3TtzyonHMXBAfz6ZO9vrWNXycnzjoralOuree8YSHx/Px7PnsWTJYoYOHsThbdqQlXWY19EqpbyR51pml/KmNW7MVYMGM3/eXAryC7yOA8Bj7y3hxn99SWGghKym9Xnjpo58v2Y7yYlx3H72UQx4cA6rfs7l7gva8cRVJ3LuA3MAuGvgMSTVi+XEke9zYP16vHbj6fy0xc8r83M8fTwu7Q/FgQBNmjbj6Sn/plmz5nwyZza33nQ9r705lfT0Fl7Hq5SX47tfH2H7/X4+/GAGQ4YOx5ecTPvjs+nUuQvT3nnb62iVUt7Icy2za3m7de9Bl67dSG2Y6nWUMss2/EphoAQAay0WS0ZaMt2PacbUL9exbMOvFBVbHn53MScfnkZGWjIAPY5txoT3l7GrsJiftvh56ZPVXHRqpoePxL39Icnn49ohQ0lPb0FMTAwdz+hMenoLFi/6wetolfJ6fKNS2MaYU40xzYK36xlj7jbGfBn8GmOMSYhGjj3l5KwmLi6WzMyWZdNat27DiuXLvYhTI+WNPNcyu5a3rvrbxe1Y+Xh/Prn7TH7ekc9H328EwJjf5tl9u03zBr+btvt263L3ecH1/WHL5s3k5KymVassr6NUyuvxjdYR9pRytx8AOgPjgHuALsB9UcpRwS6/n+TklArTUlLq4/fneRGnRsobea5ldi1vXXX7i1+TNfRt+v9jFtMXrqcwUMLHP2yiX3YLjkhvQGJ8DDf2OYKSEktSQiwAH3+/iaE9W5NcL47MtGQuPDWz7D6vuLw/FBUVMXLEzfTtfw4tD23ldZxKeT2+0SrsZtbaDcHb/YF+1tr/WGvfDH5/QXULG2OuNsYsMMYseOapyWELleTzkZeXW2Fabl4uPl9y2LYRTsobea5ldi1vXVZi4X/Lt9CsURKXdzqUuYt/5v53FvH0NSfzv7+dxdrNfnILAmzYtguAO1/+mvyiYubfcyZThpzCW/9by4btuzx9DK7uDyUlJdx5+63ExcczYuQor+NUyevxjdZFZ2uMMSdYa78ACvbYbhyQVN3C1trJwGSA/AA2XKEyMjIJBIrJyVlNRkYmAMuWLqFVVt08HaO8kedaZtfyuiA2xpCZVnoUNWXWSqbMWgnAoY1TuL53G5as3wnAdn8RQ575omy5288+iq9WbYt+4HJc3B+stYz56x1s2bKZx594ivj4eK8jVcnr8Y3WEfZY4FVjzJ+Bp4FpxphLjTGXAtOAF6OUowKfz0fX7t2ZOP4x/H4/Xy38klkzP6JPv/5exKmR8kaea5ldyxsIBCgoKKC4pITikmIKCgoIBAKe5Tmwfj36n9ACX71YYgyccWQTzjnxYOYu+Zl6cTFlz0mnH5DE/X9qz9MfLWeHvwiAjLRkGiUnEGOgS9smXNqxJY+8u9izxwLu7Q8A48aOZtXKFTw2YRKJiYk1L+Ahr8fXWBu2A9bqN2RMd2AMkA3s/hPqJ+BZ4G5rbUg/teE8wobS19SNHjWSTz+dT2rDVIbfcBO9+vQN5ybCSnkjz7XMLuV9YsJ4Jk18vMK0awZfx7VDhoZl/S0Hv1Gr+Q9MSeCpa07iyBYNiTGGn7b6eeaj5bzwyWoaJMXz5i2dyExLJjc/wCvzV/P3t36gJPgbqO/x6Yy94Fga+uJZsSmXcW98z6xFm2q1/VUTB9Rq/lBEen8IZ2WsX7+OXj26kJCQQGzsbyde7xx9F7379AvLNspfGBgOkR7fxDiqTBy1wi7boDExQBNgl7V2e22XD3dhi8gfR20L22uRKOxIi3Jl7LNwF3akVVfYUX/jFGttCbChxhlFRESkzH79xikiIiKuUGGLiIg4QIUtIiLiABW2iIiIA1TYIiIiDlBhi4iIOECFLSIi4gAVtoiIiANU2CIiIg5QYYuIiDhAhS0iIuIAFbaIiIgDVNgiIiIOUGGLiIg4IOqfh72vXPs8bMeG17nPjtX4issOuniK1xFqbfOLV3gd4Q+tus/D1hG2iIiIA1TYIiIiDlBhi4iIOECFLSIi4gAVtoiIiANU2CIiIg5QYYuIiDhAhS0iIuIAFbaIiIgDVNgiIiIOUGGLiIg4QIUtIiLiABW2iIiIA1TYIiIiDlBhi4iIOECFLSIi4oD9vrB3bN/O9cOG0CG7HT27dWb6tKleR6pSYWEhY0aN5KzunTnlxOMYOKA/n8yd7XWsark0vruNvO1mup1xGqd2aE+/3mfyn9df8zpSlV564XkuGngu2e3aMmrkCK/jhMS1faKu5m3VtD6bn/8TTw89HYCORzXl8wf689OzF5PzzIW8dHNnmjXylc2fEBfDxGtPZf2Ui1kx+QKu632kV9ErcG0f9jJvXFS3Vgfde89Y4uPj+Xj2PJYsWczQwYM4vE0bsrIO8zra7xQHAjRp2oynp/ybZs2a88mc2dx60/W89uZU0tNbeB2vUi6N725/uWoQY+6+l4SEBFatXMGVf76MNkccwZFHtfU62u+kNW7MVYMGM3/eXAryC7yOExLX9om6mveh/zuJhSs2l32/5Kft9B83g43bdpEQF8OoC47jkatO4oJ/zARg5PntyGragCOHvE6T1CSmj+7Jkp928OE367x6CIB7+7CXeffrI2y/38+HH8xgyNDh+JKTaX98Np06d2HaO297Ha1SST4f1w4ZSnp6C2JiYuh4RmfS01uweNEPXkerlGvju1tW1mEkJCQAYIzBGMPatWs8TlW5bt170KVrN1IbpnodJSSu7RN1Ne95p7Rkh7+QWd9vKJv28458Nm7bVfZ9cYmlVdMGZd9f0imLv7/xDdvzClm6bgdTPlrGpWdkRTV3ZVzbh73Mu18Xdk7OauLiYsnMbFk2rXXrNqxYvtzDVKHbsnkzOTmradXK+x+6yrg8vuPuHsNJ2cdydt+zOCgtjdM7dvI60h+Ca/tEXcxbPymeOwa2Y8RzX/zuvhYHJvPTsxez+fk/MbxvWx5++3sAUpMTaHaAj+9ztpbN+93qrRxxsBslKaWickrcGPMo8Kq1dl40theqXX4/yckpFaalpNTH78/zKFHoioqKGDniZvr2P4eWh7byOk6lXB7fO0aNYcTIUXz7zVcs+OJ/xMcneB3pD8G1faIu5h11wXH86+MfWb/V/7v7ftqSR4s/v0ij5ASu6HY4y9bvACA5sfRX/Q5/Udm8O/yFpCTGRye0hEW0jrCHAO8ZY5YbY/5qjMmozcLGmKuNMQuMMQueeWpy2EIl+Xzk5eVWmJabl4vPlxy2bURCSUkJd95+K3Hx8YwYOcrrOFVydXx3i42N5bj22WzauJHXXnnJ6zh/CK7tE3Ut79EZB9D56GY8Pm1RtfNtyyvkhVkreOWWLsTGGPLyAwA0SPqtoBv4EsjNL6pqFVIHReuis11AM+A84DJglDHmE2AK8Lq1tto/V621k4HJAPkBbLhCZWRkEggUk5OzmoyMTACWLV1Cq6y6eYoZwFrLmL/ewZYtm3n8iaeIj6+7fyG7OL6VKS4urrPPYbvGtX2iruU9/aimHJKWwpInzgdKj5xjYwxt0lM5bUTFq9fjYg2NU5NokBTPtrxCNmz10zajER9/V/q899EZjVi8dnvUH4PsvWgdYVtrbZ619jlrbVcgC/gIGAlsNMZMiVKOCnw+H127d2fi+Mfw+/18tfBLZs38iD79+nsRJyTjxo5m1coVPDZhEomJiV7HqZaL47t1yxben/4ufn8excXFzJ83l/fee5cOJ53sdbRKBQIBCgoKKC4pobikmIKCAgKBgNexquTaPlHX8j774VKOHvofTr7lHU6+5R2e+WAp/134E2ePm0G/Ew/hsGYNMAYOql+Pv19+Al+v3MK2vEIAXpyzgtsGHEtqcgKHN2/IFV0P5/lZ3l874No+7GVeY23YDlir3ogxO621Daq47xTgMmvtNaGsK5xH2FD6GsvRo0by6afzSW2YyvAbbqJXn75hW384h3f9+nX06tGFhIQEYmN/Ozly5+i76N2nX1i2YUxYVlPGpfEF2Lp1K7fcOIylS5dgS0po1jydiy75EwPOGxiW9Yd7fJ+YMJ5JEx+vMO2awddx7ZCh4d1QGEV6nwi3SOY96OIp+7T8yPPbcWjT+lw5fi7X9GzDdX2OIq1BIrn5Aeb+sJFRLyxg7ebSE5gJcTE8ctXJnN0hg/zCYh56+zsef7f6U+uV2fziFfuUeU+u7cORzpsYR5W/JaJV2L9aa+uHY13hLuxIi8LwhlW4CyXSNL7isn0tbC+Eu7ClouoKOyqnxMNV1iIiIvur/fp12CIiIq5QYYuIiDhAhS0iIuIAFbaIiIgDVNgiIiIOUGGLiIg4QIUtIiLiABW2iIiIA1TYIiIiDlBhi4iIOECFLSIi4gAVtoiIiANU2CIiIg5QYYuIiDhAhS0iIuIAY631OkOt5AdwKrBjw4up8qPTJRxc2x9co/038g6/4R2vI9TK4gf7eh2hVpITqt6LBpIYIQAAF0NJREFUdYQtIiLiABW2iIiIA1TYIiIiDlBhi4iIOECFLSIi4gAVtoiIiANU2CIiIg5QYYuIiDhAhS0iIuIAFbaIiIgDVNgiIiIOUGGLiIg4QIUtIiLiABW2iIiIA1TYIiIiDtjvC/ulF57nooHnkt2uLaNGjvA6TrUKCwsZM2okZ3XvzCknHsfAAf35ZO5sr2NVa8f27Vw/bAgdstvRs1tnpk+b6nWkarm0P4B7+4RreUH78L565LL2LLinBz/84yxmjerChScfUnZfn+Oa89EdnVl0fy8+GtmZHsc0rbDsIQf6eHbQiSy6vxdf/+1MRvY/Mtrxf2f9up8Yeu3VdDrlRLqfcRp/HzeWQCAQlW3HRWUrdVha48ZcNWgw8+fNpSC/wOs41SoOBGjStBlPT/k3zZo155M5s7n1put57c2ppKe38Dpepe69Zyzx8fF8PHseS5YsZujgQRzepg1ZWYd5Ha1SLu0P4N4+4Vpe0D68rybO+JFbX/yawkAJrZqk8MqwU/jhpx38vLOARy5rz5VP/Y9Zi36my1GNeeIv2Zwy+kO25BYSH2t4YcjJPDd3FYOf/ZKSEkvLxilePxz+ds9YDjjgAGZ8PJdff93J4Kv+wmuvvMhFl1wW8W3v90fY3br3oEvXbqQ2TPU6So2SfD6uHTKU9PQWxMTE0PGMzqSnt2Dxoh+8jlYpv9/Phx/MYMjQ4fiSk2l/fDadOndh2jtvex2tSi7tD+DePuFaXu3D+27Zxl8pDJQA8P/t3XeYVOXZx/HvzRZwd5EFUcQFKYuCNajEjgJSLDQlMRJjNPqKAmKJJUpA1FiSvBoLFtRYSDRGNMaCJUWCApLXhqLSQlsFBGUpCyws7O79/nEOuKxbzeycOfD7XNdczJw9c57fPDzX3HPKzOPu4NCuZTatc5tQtHkbU+d8BcCUz76iuKSMdi2zAfjhMfuzqmgLv//XYjZvLaOktJx5K4oiex3bLV++jD79TqNx48a0bLk3x53YnUULFyal7d2+YMdZ4erVFBQsJT+/U9RRqlRQsJT09DTat++wY1nnzl2SNrh3R6k+JipL9bwaw4lx69mHMf+u05k69hRWFW1hymermP35Ohau3ECfQ1vRyKDv4fuytbScuWFRPqJ9c5YVFjNx+DF8dEc/nr38eDq3bhrxK4Ef/+Sn/O2N19i8eTNfrVrFO9OncfyJ3ZPSdlIOiZtZI2AEcAjwuru/bGa/AU4DPgZ+7u5fJyPLrmLbtm2Mvv4aBgw6kw4d86OOU6XNxcVkZ+98CCsnpynFxZsiSrRri8OYqCgOeTWGE2PMpE+48blPOKpDC449YC+2lpZT7vCXd5dx3wVH0Ti9EdvKyhn++Pts3loGQOvcJhx3YEsueuRdZsz/mgt7dOSxYUfT89YpbCvzyF7Lkd2+zwvPT+Kk47pRVlbGgIGD6dmrd1LaTtYe9r3AMGADcJuZPQ50BsYC2cD4mp5sZsPM7H0ze/+xRx9p8LCprry8nDE3XEd6RgbXjx4bdZxq7ZGVxaZNG3datnHTRrKysiNKtOuKy5jYLi55NYYTp9zhvcVraJ27B+d1b8+JnVsyevDB/OjeGeRfNZkf3vsOvx3alYPz9gRgy7Yy3lu0hqlzvmJbmfPwm4vIzc6k077R7WWXl5dz2aUX06t3X2a8O4sp02ZSVFTEvXffmZT2k1WwhwC93f064FTgfOBn7v4ScCHQq6Ynu/sj7t7N3btddPGwhk+bwtydm278JYWFq7nr7vFkZGREHala7dq1p7S0jIKCpTuWLZg/j/xOqXn4M67iNCYgXnk1hhMvrZHRrmU2B+c14/8WFjL7i/W4w+zP1zGrYC0ndt4bgLkrinCi25Ouyvr161n55Qp+NPRcMjMzyc1tzsDBZzFj2ttJaT9ZBbsJsDa8vwYoB7Z/bN1AhFerl5aWUlJSQll5OWXlZZSUlCTtEv3v4rZbxrFk8SLue2ACTZo0iTpOjbKysjilTx8eHH8fxcXFzPrwA6ZOeZP+AwdFHa1acRsPEK8xAfHKqzH839krJ5MBR+5HVmYajQxO6rI3g47KY8b8r/n483Ucnd9ixx71IW325Oj8vXacw/7re8s4sn1zTuzckkYGF/XsyNqNW1m4ckMkrwWgefPm5OW14flnn6G0tJQNRUVMfvlFDjjgwKS0b+4N/wnGzF4FVgGTgKEE57KfBx4AhgOnuXvPumxrS2liP3I99MB4Jjx4/07LLh1xGcNHjkrI9hPZvStWLOf0vr3IzMwkLe2bzzhjxt3MGf0HJqQNs4RsZof169YxbuxoZs58h9xmuVxx1dWc3n9AYhtJoDiNB0jOmEikhs6b6PELGsOVHXjVy3Vet0VOJhMu7MZBec1oZLB87WaeeGsxz7zzOQDnn9Sei3rk07JpY9ZsLGHitKU8OmXRjuef+r3WjB50MHvlZPLpsvWMnfQJC+pZsOfeldj/q/nz5nLnb25nwfz5pKU14vtHH8t1N4xhr5YtE7L97MzqR3GyCnY74EGgPXAPMA14A2gLLAHOcvfZddlWogt2Q0tC9yZUQ7zhyTfiNh7iRuO34dWnYKeCRBfshlZTwU7KoWh3LwDOqLjMzDoALdy9MBkZRERE4iyyc8ce7NqrWIuIiNSBfjhFREQkBlSwRUREYkAFW0REJAZUsEVERGJABVtERCQGVLBFRERiQAVbREQkBlSwRUREYkAFW0REJAZUsEVERGJABVtERCQGVLBFRERiQAVbREQkBlSwRUREYsCCWS7jY0sp8QosIlKNmL39AmAWdYL6ybvomagj1EvhxKHV9rD2sEVERGJABVtERCQGVLBFRERiQAVbREQkBlSwRUREYkAFW0REJAZUsEVERGJABVtERCQGVLBFRERiQAVbREQkBlSwRUREYkAFW0REJAZUsEVERGJABVtERCQGVLBFRERiQAVbREQkBnb7gr1+3TquvHwkx3Tryqm9e/La5FeijlQj5W1Yzzz9FEPPPotuXQ9l7Ojro45TJ3HrY+VtOFu3buWmsaM5rU9Pjj/6CM4eMojp096KOlaNUrV/O7bKYfmjZzPhkuMAaNWsCU9d2Z3P7hlE4cShtG2ZvdP6487uyuzfDWTphB/w0V0Duar/wQnPlJ7wLcbM7bfeQkZGBv96awbz5s1l1IhLOLBLFzp1OiDqaFVS3oa19z77cPElI3hnxjRKtpREHadO4tbHyttwykpLabVva37/5B9p3Xo/pr/9FtddfSXP/fUV8vLaRB2vSqnav7/9aTdmLSnc8bjcYcrsL7nnlTn87ca+31r/6bcX8b8vfkLx1jJaN9+D56/tyX++LGLyB8sSlmm33sMuLi7mn//4OyNHXUFWdjZHHtWNk3v2YvLLL0UdrUrK2/B69+lLr1N6k9ssN+oodRK3PlbehrVHVhbDR44iL68NjRo14qQePcnLa8PcOZ9FHa1Kqdq/Zx6zP+uLt/H2nFU7ln1dtIXHpyxk1pI1VT5n4coNFG8t2/G4vNzp0KppQnMlrWCbWSczu9nM/mJmr5vZo2Z2sZllJCtDZQUFS0lPT6N9+w47lnXu3IVFCxdGFalGyiuVxa2PlTe5ClevpqBgKfn5naKOUqVU7N+mTdK5/qzDGPunD+v93CvOOIiCh3/Ap/cMJqtxOn+ZuTSh2ZJSsM1sMPARcCzQFOgFNAYuAOaZWcdk5Khsc3Ex2dk5Oy3LyWlKcfGmKOLUSnmlsrj1sfImz7Zt2xh9/TUMGHQmHTrmRx2nSqnYvzcMOZyn31rMirWb6/3ce1+dS7tLnqfH2DeY9M4SijZvS2i2ZO1h/xYY4O793L0vMADY291PAB4Cxtf0ZDMbZmbvm9n7jz36SMJC7ZGVxaZNG3datnHTRrKysqt5RrSUVyqLWx8rb3KUl5cz5obrSM/I4PrRY6OOU61U699D98/l5EP25aG/zf+vtvPJ52vZsrWMX5x5WIKSBZJVsPcBplZ4PAXoFt5/EOhe05Pd/RF37+bu3S66eFjCQrVr157S0jIKCpbuWLZg/jzyO6Xm4SPllcri1sfK2/DcnZtu/CWFhau56+7xZGREdtaxVqnWvyd0aUXbltl8/LuBzLl3MCNP60L/bm2YcnO/em8rPa0RHfbJqX3FekhWwf4AuLzC4yuB7VdBlAGlScqxk6ysLE7p04cHx99HcXExsz78gKlT3qT/wEFRxKmV8ja80tJSSkpKKCsvp6y8jJKSEkpLIxmedRK3PlbehnfbLeNYsngR9z0wgSZNmkQdp0ap1r9/mLqQbte+Qo8b36DHjW/w5L8W8o+PV/DDO6cC0DijEY3Tg7LZOL0RjTOC+2Zwfo98mmUFH46O7NiCC085YKeL1hLB3D2hG6yyEbMuwEtA63DRV8Bgd//UzA4DznP36+qyrS2lJDTw+nXrGDd2NDNnvkNus1yuuOpqTu8/IJFNJJTyNqyHHhjPhAfv32nZpSMuY/jIURElql3c+lh5v5Hot98VK5Zzet9eZGZmkpb2zbd2x4y7mTP6D0xIG2YJ2cwODT0e8i565js/97rBh9KxVVMufXgmAIUTh35rnb3OfwYzePbnPTiyYwsy0huxct1m/jxtCXdPnlPvNgsnDq22h5NSsAHMLA3oEj6c7+7fabcl0QVbRCQqSXr7TahEF+yG9t8U7CjUVLCT9sMp7l7GN4fBRUREpB526x9OERERiQsVbBERkRhQwRYREYkBFWwREZEYUMEWERGJARVsERGRGFDBFhERiQEVbBERkRhQwRYREYkBFWwREZEYUMEWERGJARVsERGRGFDBFhERiQEVbBERkRhQwRYREYkB8zjOoN4AzGyYuz8SdY66Ut6GF7fMytuwlLdhKW/ttIf9jWFRB6gn5W14ccusvA1LeRuW8tZCBVtERCQGVLBFRERiQAX7G7E5dxJS3oYXt8zK27CUt2Epby100ZmIiEgMaA9bREQkBlSwRUREYmC3L9hm1sLM/mpmm8yswMx+HHWmmpjZZWb2vpmVmNmTUeepjZk1NrPHwr7dYGYfmdlpUeeqiZk9ZWZfmlmRmS0ws/+JOlNtzOwAM9tiZk9FnaU2ZjY1zLoxvM2POlNtzOwcM5sbvk8sMrPuUWeqSoU+3X4rM7PxUeeqiZm1N7PXzGytma00s/vNLD3qXNUxs4PMbIqZrTezhWZ2ZrLa3u0LNvAAsBVoBZwLPGRmh0QbqUYrgFuBx6MOUkfpwBfAyUAzYAwwyczaR5ipNncA7d19T2AgcKuZHRVxpto8ALwXdYh6uMzdc8Jb56jD1MTM+gC/AX4GNAVOAhZHGqoaFfo0B9gX2Aw8F3Gs2jwIfAW0BroSvFeMiDRRNcIPEi8Bk4EWBN/FfsrMDkxG+7t1wTazbGAIMNbdN7r7dOBl4Lxok1XP3V9w9xeBwqiz1IW7b3L3m9x9qbuXu/tkYAmQsgXQ3T9z95LtD8NbfoSRamRm5wDrgDejzrKLuhm4xd3/HY7h5e6+POpQdTCEoBBOizpILToAk9x9i7uvBN4AUnWnqQuwH3C3u5e5+xRgBkmqGbt1wQYOBErdfUGFZR+TuoMl9sysFUG/fxZ1lpqY2YNmVgzMA74EXos4UpXMbE/gFuDnUWeppzvMbLWZzTCzHlGHqY6ZpQHdgL3Dw5/LwkO2e0SdrQ7OB/7gqf9VoHuAc8wsy8zygNMIinZcGHBoMhra3Qt2DlBUadl6gsNekmBmlgE8DUx093lR56mJu48gGAfdgReAkpqfEZlfAY+5+7Kog9TDL4COQB7Bd1lfMbNUPYLRCsgAfkAwFroCRxCc2klZZtaO4NDyxKiz1MHbBDtJRcAy4H3gxUgTVW8+wVGLa80sw8z6EvRzVjIa390L9kZgz0rL9gQ2RJBll2ZmjYA/ElwvcFnEceokPOQ1HWgDDI86T2Vm1hXoDdwddZb6cPf/c/cN7l7i7hMJDimeHnWuamwO/x3v7l+6+2rgd6Ru3u3OA6a7+5Kog9QkfF94g+BDcTbQEmhOcM1AynH3bcBg4AxgJXA1MIngg0aD290L9gIg3cwOqLDse6T44dq4MTMDHiPYWxkSDvo4SSc1z2H3ANoDn5vZSuAaYIiZfRhlqO/ACQ4rphx3X0vwZlzxsHKqH2IG+Cnx2LtuAewP3B9+gCsEniCFPxC5+2x3P9nd93L3fgRHi95NRtu7dcF2900En+xuMbNsMzsBGESwJ5iSzCzdzJoAaUCamTVJ5a9AhB4CDgIGuPvm2laOkpntE36FJ8fM0sysHzCU1Lyg6xGCDxJdw9sE4FWgX5ShamJmuWbWb/u4NbNzCa66TuVzlk8Ao8Kx0Ry4iuAq4ZRkZscTnG5I9avDCY9YLAGGh+Mhl+Dc++xok1XPzA4Px2+WmV1DcHX7k8loe7cu2KERwB4E5yWeAYa7eyrvYY8hOEx3PfCT8H7Knk8Lz6VdQlBQVlb4fui5EUerjhMc/l4GrAXuBK5095cjTVUFdy9295XbbwSneLa4+9dRZ6tBBsHXEr8GVgOjgMGVLvxMNb8i+MrcAmAuMAu4LdJENTsfeMHd43Jq7yzgVIIxsRDYRvChKFWdR3Ah6lfAKUCfCt8qaVD6LXEREZEY0B62iIhIDKhgi4iIxIAKtoiISAyoYIuIiMSACraIiEgMqGCLiIjEgAq2yC7EzJ40s1vD+92TNde0mbmZdarmb1PrOqe4mS01s97fMcN3fq5IHKhgiyRZWFg2hz8gsyossjmJbsfdp9Vlrmkzu8DMpie6fRFJLBVskWgMcPcc4EiC6Ru/9Wt1MfjJWRFJIhVskQi5+3LgdcL5dMNDyyPN7D/Af8Jl/c3sIzNbZ2bvmNnh259vZkeY2YdmtsHMngWaVPhbDzNbVuFxWzN7wcy+NrPCcF7ngwh+g/y4cI9/XbhuYzO708w+D48CTKg4B7SZXWtmX5rZCjO7sK6v18zyzWxK2P5qM3s6/P3oir5vZnPMbK2ZPRH+dv7251fbFyK7OhVskQiZWVuCmYlmVVg8GDgGONjMjgAeJ/g99r2Ah4GXw4KaSTBv8B8JZj16DhhSTTtpBBNWFBDM8JUH/Nnd5wKXAjPdPcfdtxfPXwMHEvwGfKdw/RvDbZ1KMDNYH+AAgik+6/ySgTuA/QgmhGkL3FRpnXMJJjDJDzOMCdutti/q0b5IbKlgi0TjxXBvdjrwFnB7hb/d4e5rwpnNhgEPh3NIl4XzR5cAx4a3DOAed9/m7s8TTFJRlaMJiuS17r7J3beEc31/Szgd6jDgqjDHhjDfOeEqZwNPuPun4Yx3N9X1Rbv7Qnf/RziV4tcEc0ufXGm1+939C3dfQzDJxtBweU19IbLL0zkykWgMdvd/VvO3Lyrcbwecb2ajKizLJCi+Diz3nWfwKahmm22BAncvrUO2vYEs4IOgdgPBnnFaeH8/4IM6tPktZtYKuBfoDjQl2GlYW2m1iq+/IGwPau4LkV2e9rBFUk/FAvwFcJu751a4Zbn7MwRT/OVZhaoK7F/NNr8A9q/mQrbKU/atJpi29ZAKbTYLL5IjbLdtHdqsyu1he4e5+54EU8RapXUqb3tFhddQXV+I7PJUsEVS26PApWZ2jAWyzewMM2sKzARKgcvNLMPMziI49F2VdwkK7a/DbTQxsxPCv60C2oTnxHH38rDdu81sHwAzyzOzfuH6k4ALzOxgM8sCxtXj9TQlmLd7vZnlAddWsc5IM2tjZi2AXwLP1qEvRHZ5KtgiKczd3wcuBu4nOHS8ELgg/NtW4Kzw8RrgR8AL1WynDBhAcAHZ58CycH2AKcBnwEozWx0u+0XY1r/NrAj4J9A53NbrwD3h8xaG/9bVzQRfZVsPvFpN3j8BfwcWA4uAW2vrC5Hdge18+ktERERSkfawRUREYkAFW0REJAZUsEVERGJABVtERCQGVLBFRERiQAVbREQkBlSwRUREYkAFW0REJAZUsEVERGLg/wFQeQ0PqO3ioAAAAABJRU5ErkJggg==\n"
          },
          "metadata": {
            "needs_background": "light"
          }
        }
      ],
      "source": [
        "cm = confusion_matrix(y_test, y_pred)\n",
        "\n",
        "plt.figure(figsize=(7,7))\n",
        "sns.heatmap(cm, fmt='g', cbar=False, annot=True, cmap='Blues')\n",
        "plt.title('confusion_matrix')\n",
        "plt.ylabel('True label')\n",
        "plt.xlabel('Predicted label')\n",
        "plt.show()"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "tags": [],
        "id": "SPfB9lnMNzhb"
      },
      "source": [
        "# Submission\n",
        "\n",
        "Last but note least, we create our submission to the Kaggle competition. The submission is just a `csv` file with the specified columns."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "tags": [
          "skip"
        ],
        "id": "VkMyLyUONzhb"
      },
      "outputs": [],
      "source": [
        "test = all_data_X[ntrain:].copy()\n",
        "submission_file = np.argmax(model.predict(test), axis=-1)\n",
        "ss['Label'] = submission_file"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "tags": [
          "skip"
        ],
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 206
        },
        "id": "HaOYuW69Nzhc",
        "outputId": "2feb0c62-e6df-410f-d7df-1367c793fb9e"
      },
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "   ImageId  Label\n",
              "0        1      2\n",
              "1        2      0\n",
              "2        3      9\n",
              "3        4      9\n",
              "4        5      3"
            ],
            "text/html": [
              "\n",
              "  <div id=\"df-359c65d7-e60c-495b-93f6-fc668b7847cd\">\n",
              "    <div class=\"colab-df-container\">\n",
              "      <div>\n",
              "<style scoped>\n",
              "    .dataframe tbody tr th:only-of-type {\n",
              "        vertical-align: middle;\n",
              "    }\n",
              "\n",
              "    .dataframe tbody tr th {\n",
              "        vertical-align: top;\n",
              "    }\n",
              "\n",
              "    .dataframe thead th {\n",
              "        text-align: right;\n",
              "    }\n",
              "</style>\n",
              "<table border=\"1\" class=\"dataframe\">\n",
              "  <thead>\n",
              "    <tr style=\"text-align: right;\">\n",
              "      <th></th>\n",
              "      <th>ImageId</th>\n",
              "      <th>Label</th>\n",
              "    </tr>\n",
              "  </thead>\n",
              "  <tbody>\n",
              "    <tr>\n",
              "      <th>0</th>\n",
              "      <td>1</td>\n",
              "      <td>2</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>1</th>\n",
              "      <td>2</td>\n",
              "      <td>0</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>2</th>\n",
              "      <td>3</td>\n",
              "      <td>9</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>3</th>\n",
              "      <td>4</td>\n",
              "      <td>9</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>4</th>\n",
              "      <td>5</td>\n",
              "      <td>3</td>\n",
              "    </tr>\n",
              "  </tbody>\n",
              "</table>\n",
              "</div>\n",
              "      <button class=\"colab-df-convert\" onclick=\"convertToInteractive('df-359c65d7-e60c-495b-93f6-fc668b7847cd')\"\n",
              "              title=\"Convert this dataframe to an interactive table.\"\n",
              "              style=\"display:none;\">\n",
              "        \n",
              "  <svg xmlns=\"http://www.w3.org/2000/svg\" height=\"24px\"viewBox=\"0 0 24 24\"\n",
              "       width=\"24px\">\n",
              "    <path d=\"M0 0h24v24H0V0z\" fill=\"none\"/>\n",
              "    <path d=\"M18.56 5.44l.94 2.06.94-2.06 2.06-.94-2.06-.94-.94-2.06-.94 2.06-2.06.94zm-11 1L8.5 8.5l.94-2.06 2.06-.94-2.06-.94L8.5 2.5l-.94 2.06-2.06.94zm10 10l.94 2.06.94-2.06 2.06-.94-2.06-.94-.94-2.06-.94 2.06-2.06.94z\"/><path d=\"M17.41 7.96l-1.37-1.37c-.4-.4-.92-.59-1.43-.59-.52 0-1.04.2-1.43.59L10.3 9.45l-7.72 7.72c-.78.78-.78 2.05 0 2.83L4 21.41c.39.39.9.59 1.41.59.51 0 1.02-.2 1.41-.59l7.78-7.78 2.81-2.81c.8-.78.8-2.07 0-2.86zM5.41 20L4 18.59l7.72-7.72 1.47 1.35L5.41 20z\"/>\n",
              "  </svg>\n",
              "      </button>\n",
              "      \n",
              "  <style>\n",
              "    .colab-df-container {\n",
              "      display:flex;\n",
              "      flex-wrap:wrap;\n",
              "      gap: 12px;\n",
              "    }\n",
              "\n",
              "    .colab-df-convert {\n",
              "      background-color: #E8F0FE;\n",
              "      border: none;\n",
              "      border-radius: 50%;\n",
              "      cursor: pointer;\n",
              "      display: none;\n",
              "      fill: #1967D2;\n",
              "      height: 32px;\n",
              "      padding: 0 0 0 0;\n",
              "      width: 32px;\n",
              "    }\n",
              "\n",
              "    .colab-df-convert:hover {\n",
              "      background-color: #E2EBFA;\n",
              "      box-shadow: 0px 1px 2px rgba(60, 64, 67, 0.3), 0px 1px 3px 1px rgba(60, 64, 67, 0.15);\n",
              "      fill: #174EA6;\n",
              "    }\n",
              "\n",
              "    [theme=dark] .colab-df-convert {\n",
              "      background-color: #3B4455;\n",
              "      fill: #D2E3FC;\n",
              "    }\n",
              "\n",
              "    [theme=dark] .colab-df-convert:hover {\n",
              "      background-color: #434B5C;\n",
              "      box-shadow: 0px 1px 3px 1px rgba(0, 0, 0, 0.15);\n",
              "      filter: drop-shadow(0px 1px 2px rgba(0, 0, 0, 0.3));\n",
              "      fill: #FFFFFF;\n",
              "    }\n",
              "  </style>\n",
              "\n",
              "      <script>\n",
              "        const buttonEl =\n",
              "          document.querySelector('#df-359c65d7-e60c-495b-93f6-fc668b7847cd button.colab-df-convert');\n",
              "        buttonEl.style.display =\n",
              "          google.colab.kernel.accessAllowed ? 'block' : 'none';\n",
              "\n",
              "        async function convertToInteractive(key) {\n",
              "          const element = document.querySelector('#df-359c65d7-e60c-495b-93f6-fc668b7847cd');\n",
              "          const dataTable =\n",
              "            await google.colab.kernel.invokeFunction('convertToInteractive',\n",
              "                                                     [key], {});\n",
              "          if (!dataTable) return;\n",
              "\n",
              "          const docLinkHtml = 'Like what you see? Visit the ' +\n",
              "            '<a target=\"_blank\" href=https://colab.research.google.com/notebooks/data_table.ipynb>data table notebook</a>'\n",
              "            + ' to learn more about interactive tables.';\n",
              "          element.innerHTML = '';\n",
              "          dataTable['output_type'] = 'display_data';\n",
              "          await google.colab.output.renderOutput(dataTable, element);\n",
              "          const docLink = document.createElement('div');\n",
              "          docLink.innerHTML = docLinkHtml;\n",
              "          element.appendChild(docLink);\n",
              "        }\n",
              "      </script>\n",
              "    </div>\n",
              "  </div>\n",
              "  "
            ]
          },
          "metadata": {},
          "execution_count": 26
        }
      ],
      "source": [
        "ss.to_csv('sub.csv', index=False)\n",
        "ss.head()"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "iq7k4Eg1Nzhc"
      },
      "outputs": [],
      "source": [
        ""
      ]
    }
  ],
  "metadata": {
    "kernelspec": {
      "display_name": "Python 3",
      "language": "python",
      "name": "python3"
    },
    "kubeflow_notebook": {
      "autosnapshot": true,
      "experiment": {
        "id": "new",
        "name": "digit-recognizer-kale"
      },
      "experiment_name": "digit-recognizer-kale",
      "katib_metadata": {
        "algorithm": {
          "algorithmName": "grid"
        },
        "maxFailedTrialCount": 3,
        "maxTrialCount": 12,
        "objective": {
          "objectiveMetricName": "",
          "type": "minimize"
        },
        "parallelTrialCount": 3,
        "parameters": []
      },
      "katib_run": false,
      "pipeline_description": "Performs Preprocessing, training and prediction of digits",
      "pipeline_name": "digit-recognizer-kale",
      "snapshot_volumes": true,
      "steps_defaults": [
        "label:access-ml-pipeline:true",
        "label:access-rok:true"
      ],
      "volume_access_mode": "rwm",
      "volumes": [
        {
          "annotations": [],
          "mount_point": "/home/jovyan",
          "name": "arikkto-workspace-7xzjm",
          "size": 5,
          "size_type": "Gi",
          "snapshot": false,
          "type": "clone"
        }
      ]
    },
    "language_info": {
      "codemirror_mode": {
        "name": "ipython",
        "version": 3
      },
      "file_extension": ".py",
      "mimetype": "text/x-python",
      "name": "python",
      "nbconvert_exporter": "python",
      "pygments_lexer": "ipython3",
      "version": "3.6.9"
    },
    "colab": {
      "name": "digit-recognizer-orig.ipynb",
      "provenance": []
    }
  },
  "nbformat": 4,
  "nbformat_minor": 0
}
